﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

using Newtonsoft.Json.Utilities;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Kortex.WallManagerControl.REST_Server;


namespace Barco.Web.KPHttpServer
{


    public class MyWebServer
    {
        #region Local Variable
        private TcpListener myListener;
        private int mPort = 8080; // Select any free port you wish
        
        private bool isAlive = true;
        
        private string mTempDir;
        public RestServer ReqConsumer = null;
        private bool isStarted = false;
        

        Thread th;
        
        HttpListener mListenToRemote = null;


        #endregion

        #region Public Properties
        public bool CanRunHttpServer
        {
            get
            {
                return isAlive;
            }
            set
            {
                isAlive = value;
            }
        }

        public HttpListener HttpListenerObj
        {
            get
            {
                return mListenToRemote;
            }


        }


        #endregion

        #region COnstrctor
        //The constructor which make the TcpListener start listening on the
        //given port. It also calls a Thread on the method StartListen(). 

        public MyWebServer(RestServer rstSrv)
        {
            ReqConsumer = rstSrv;
        }
        

        
        #endregion


        public string ShowRequestData(HttpListenerRequest request)
        {
            if (!request.HasEntityBody)
            {
                MessageBox.Show("No client data was sent with the request.");
                return null;
            }
            System.IO.Stream body = request.InputStream;
            System.Text.Encoding encoding = request.ContentEncoding;
            System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
            if (request.ContentType != null)
            {
                // MessageBox.Show("Client data content type "+ request.ContentType);
            }
            //MessageBox.Show("Client data content length" +  request.ContentLength64);

            //Console.WriteLine("Start of client data:");
            // Convert the data to a string and display it on the console.
            string s = reader.ReadToEnd();
            //Console.WriteLine(s);
            //MessageBox.Show(s);
            //Console.WriteLine("End of client data:");
            body.Close();
            reader.Close();
            // If you are finished with the request, it should be closed also.
            return s;
        }


        // This example requires the System and System.Net namespaces.
        public void SimpleListenerExample(string[] prefixes)
        {
            if (!HttpListener.IsSupported)
            {
                Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
                return;
            }
            // URI prefixes are required,
            // for example "http://contoso.com:8080/index/".
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");

            // Create a listener.
            HttpListener listener = new HttpListener();
            // Add the prefixes.
            foreach (string s in prefixes)
            {
                listener.Prefixes.Add(s);
            }
            listener.Start();
            Console.WriteLine("Listening...");
            // Note: The GetContext method blocks while waiting for a request. 
            HttpListenerContext context = listener.GetContext();
            HttpListenerRequest request = context.Request;

            ShowRequestData(request);

            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Construct a response.
            string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            byte[] kpBuff = new byte[250];
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();



            listener.Stop();
        }



        #region Start Server


        // This example requires the System and System.Net namespaces.
        public HttpListener httpListenerKP(string[] prefixes)
        {
            if (!HttpListener.IsSupported)
            {
                Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
                return null;
            }
            // URI prefixes are required,
            // for example "http://contoso.com:8080/index/".
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");

            // Create a listener.
            //HttpListener listener = new HttpListener();
            mListenToRemote = new HttpListener();
            // Add the prefixes.
            foreach (string s in prefixes)
            {
                mListenToRemote.Prefixes.Add(s);
            }
            mListenToRemote.Start();
            Console.WriteLine("Listening...");

            return mListenToRemote;



            //listener.Stop();
        }

        public Thread StartHttp(Int32 port_p, string TempDir)
        {
            // System.Net.IPAddress KpIp = new IPAddress(0x6b499e96);

            if (isRunning) return null;
            try
            {
                isAlive = true;
                //start listing on the given port
                // myListener = new TcpListener(KpIp,(port_p));
                //myListener.Start();
                //Console.WriteLine("Web Server Running... Press ^C to Stop...");
                //start the thread which calls the method 'StartListen'
                mPort = port_p;
                mTempDir = TempDir;
                th = new Thread(new ThreadStart(StartListen));
                th.Name = "Http Server";
                th.Start();
            
               // StartListen();


            }
            catch (Exception e)
            {
                Console.WriteLine("An Exception Occurred while Listening :" + e.ToString());
            }

            return th;

        }
        #endregion

        # region string to Byte[]
        public static byte C2b(char c)
        {
            if ((int)c < 256) return (byte)c;
            throw new Exception("character overflows a byte");
        }

        public static byte[] S2b(string value)
        {
            byte[] buffer = new byte[value.Length];
            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i] = C2b(value[i]);
            }

            return buffer;
        }
        #endregion


        public void RespondToRequester(HttpListenerContext context, string resp)
        {

            if (isAlive)
            {
                // Obtain a response object.
                HttpListenerResponse response = context.Response;
                // Construct a response.
                string responseString = resp;
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                // Get a response stream and write the response to it.


                try
                {
                    response.ContentLength64 = buffer.Length;
                    System.IO.Stream output = response.OutputStream;
                    output.Write(buffer, 0, buffer.Length);
                    // You must close the output stream.
                    output.Close();
                    //response.StatusCode = 404;
                    response.Close();
                }
                catch (HttpListenerException)
                {


                }
            }

        }


        private void RespondHtmlFile(HttpListenerContext context, string filename)
        {
            string Html = ReadFullFile(filename);

            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Construct a response.
            string responseString = Html;
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();



        }

        private void RespondImageFile(HttpListenerContext context, string filename)
        {
            byte[] ImageData = ReadFullFileBUffer(filename);

            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Construct a response.
            
            // Get a response stream and write the response to it.
            response.ContentLength64 = ImageData.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(ImageData, 0, ImageData.Length);
            // You must close the output stream.
            output.Close();



        }

        private string ReadFullFile(string FileName)
        {
            int count = 0;
            FileStream inStream = null;
            try
            {
                inStream = File.OpenRead(FileName);
            }
            catch (FileNotFoundException)
            {
                throw new ArgumentException("Projector Did not Sent any JSON for ,");
            }
            catch (FileLoadException)
            {
                throw new ArgumentException("Seems Currepted JSON Returned Try Again for ,");

            }
            catch (DirectoryNotFoundException)
            {

                throw new ArgumentException("The Temp Directory is Wrong");
            }
            catch (FieldAccessException)
            {

                throw new ArgumentException("You Do not have Enough Right on " + FileName + "File for ,");

            }
            byte[] Buff = new Byte[inStream.Length];
            count = inStream.Read(Buff, 0, (Int32)inStream.Length);
            inStream.Close();
            string sJSON = System.Text.ASCIIEncoding.ASCII.GetString(Buff);



            return sJSON;

        }

        private byte[] ReadFullFileBUffer(string FileName)
        {
            int count = 0;
            FileStream inStream = null;
            try
            {
                inStream = File.OpenRead(FileName);
            }
            catch (FileNotFoundException)
            {
                throw new ArgumentException("Projector Did not Sent any JSON for ,");
            }
            catch (FileLoadException)
            {
                throw new ArgumentException("Seems Currepted JSON Returned Try Again for ,");

            }
            catch (DirectoryNotFoundException)
            {

                throw new ArgumentException("The Temp Directory is Wrong");
            }
            catch (FieldAccessException)
            {

                throw new ArgumentException("You Do not have Enough Right on " + FileName + "File for ,");

            }
            byte[] Buff = new Byte[inStream.Length];
            count = inStream.Read(Buff, 0, (Int32)inStream.Length);
            inStream.Close();

            return Buff;

        }



        private string parseCommand(string Url)
        {
            string tmp = null;
            Int32 index = 0;
            if (Url != null)
            {
                index = Url.LastIndexOf("/");
                if (index > 0)
                {
                    tmp = Url.Substring(index);
                    tmp = tmp.Remove(0, 1);
                    Url = tmp;
                }
            }
            else
            {
                return "NULL";
            }


            return Url;

        }

        

//9868427284 Piyush Aggrwal

        public void StopServer()
        {
            isAlive = false;
            if (isStarted)
            {
                mListenToRemote.Stop();
                isStarted = false;
            }
            th.Abort();
        
        }

        public bool isRunning
        {
            get 
            {
                return isStarted;
            
            }
        
        }

        #region Listen and Server Thread

        //This method Accepts new connection and also if there is some JSON
        public void StartListen()
        {
            Byte[] bReceive = new Byte[10000];
            string[] PreFix = new string[1];
            string PreFixPort = "http://*:";
            PreFixPort += mPort.ToString();
            PreFixPort += "/";
            string HttpRoot = null;
            // RegistryKey myRegKey = Registry.LocalMachine;



            //PreFix[0] = new string("http://*:8080/".ToCharArray());
            PreFix[0] = new string(PreFixPort.ToCharArray());
            HttpListener listener = null;
            string ReadBuff = null;
            HttpListenerContext context = null;
            HttpListenerRequest request = null;
            HttpWebResponse     mWebServerReponce = null;
            Stream HttpStream = null ;
            
            string ActionURL  = String.Empty;
            string ActionJSON = String.Empty;
            



            try
            {
                //Listner Gobal to Local for Performance :))))
                listener = httpListenerKP(PreFix);
            }
            catch (HttpListenerException ep)
            {
                isStarted = false;
                MessageBox.Show("Server can not be started due to "+ ep.Message);
                return;

            }

            isStarted = true;


            while (isAlive)
            {
                // Note: The GetContext method blocks while waiting for a request. 
                try
                {
                    context = listener.GetContext();
                    request = context.Request;
                }
                catch (HttpListenerException er)
                {

                }
                finally
                {
                    // MessageBox.Show("Finally");
                }

                if (request != null && isAlive)
                if (request.HttpMethod == "POST")
                {
                    try
                    {

                        if (isAlive)
                        {
                            string RawURl = (context.Request.RawUrl);
                            ReadBuff = ShowRequestData(request);
                            
                            //ActionURL  = request.RawUrl;

                            MessageBox.Show("URL=" +RawURl+"POST data=" +ReadBuff);
                            RespondToRequester(context, "Got Post request");

                            ///ReqConsumer.PostRequest(context, ReadBuff);
                        }

                    }
                    catch(Exception er)
                    { 

                    
                    }
                                            

                }
                else if (request.HttpMethod == "GET")
                {
                    if (isAlive)
                    {
                        string RawURl = (context.Request.RawUrl);

                       // RespondHtmlFile(context,"kp.html");
                        if (RawURl == "/")
                            RespondHtmlFile(context, "kp.html");
                        else if (RawURl.Contains("include"))
                            RespondHtmlFile(context,"."+ RawURl);
                       else if (RawURl.Contains("images"))
                            RespondImageFile(context, "." + RawURl);




                       // ReqConsumer.GetRequest(context, RawURl);
                    }
                   /* try
                    {
                      
                      //  mWebServerReponce = mHttpClient.HttpCommand("GET", RequriedURl, null);
                      //  RecevJSON = mHttpClient.RunSyncCommand(mGui.Curl_path, URL, TemFile);
                    }
                    catch (UriFormatException er)
                    {
                        RespondToRequester(context, er.Message);
                        continue;
                    }
                    catch(ArgumentException er)
                    {
                        RespondToRequester(context, er.Message);
                        continue;
                    }
                    */
                    //RespondToRequester(context, GetReponceString(ResponceJSONDS, "OK", "|"));
                     //RespondToRequester(context, GetReponceString(ResponceJSONDS, mWebServerReponce,"|"));
                     
                     

                }
                else
                {
                   // RespondToRequester(context, "We Do not Support " + request.HttpMethod + " Method Right Now Try later :))))<BR> KP");

                }
            }

        }

        #endregion
    }
}
